/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef UNIT_TEST_INC_TEE_SE_API_H
#define UNIT_TEST_INC_TEE_SE_API_H

#ifndef ENABLE_TESTING
#error only in test mode
#endif

#include <stdbool.h>

#include "tee_defines.h"

/*
 * below definitions are defined by Global Platform
 * for compatibility:
 * don't make any change to the content below
 */
struct TEE_SEServiceHandleInner;
struct TEE_SEReaderHandleInner;
struct TEE_SESessionHandleInner;
struct TEE_SEChannelHandleInner;

typedef struct TEE_SEServiceHandleInner *TEE_SEServiceHandle;
typedef struct TEE_SEReaderHandleInner *TEE_SEReaderHandle;
typedef struct TEE_SESessionHandleInner *TEE_SESessionHandle;
typedef struct TEE_SEChannelHandleInner *TEE_SEChannelHandle;

#define ATR_LEN_MAX 32U
#define AID_LEN_MIN 5U
#define AID_LEN_MAX 16U

#define SE_LOGIC_CHANNEL_MAX 8U // 0 is for basic channel
#define TEE_SC_TYPE_SCP03 0x01
#define BYTE_LEN 8

typedef struct TEE_SEReaderPropertiesInner {
    bool sePresent;            // true if an SE is present in the reader
    bool teeOnly;              // true if this reader is only accessible via the TEE
    bool selectResponseEnable; // true if the response to a SELECT is available in the TEE
} TEE_SEReaderProperties;

typedef struct TEE_SEAID {
    uint8_t *buffer;    // the value of the applet's AID
    uint32_t bufferLen; // length of the applet's AID
} TEE_SEAID;

typedef enum {
    TEE_SC_BASE_KEY = 0, // A base key acc. to SCP02
    TEE_SC_KEY_SET = 1   // A key set (key-ENC, key-MAC) acc. to SCP02, SCP03
} TEE_SC_KeyType;

typedef struct TEE_SC_KeySetRefInner {
    TEE_ObjectHandle scKeyEncHandle; // Key-ENC (static encryption key)
    TEE_ObjectHandle scKeyMacHandle; // Key-MAC (static MAC key)
} TEE_SC_KeySetRef;

typedef enum {
    TEE_SC_NO_SECURE_MESSAGING = 0x00, // Nothing will be applied
    TEE_SC_AUTHENTICATE = 0x80,        // Command, Response APDU not be secured
    TEE_SC_C_MAC = 0x01,               // Command APDU shall be MAC protected
    TEE_SC_R_MAC = 0x10,               // Response APDU shall be MAC protected
    TEE_SC_CR_MAC = 0x11,              // Command, Response APDU shall be MAC
    // protected
    TEE_SC_C_ENC_MAC = 0x03, // Command APDU shall be encrypted and
    // MAC protected
    TEE_SC_R_ENC_MAC = 0x30,  // Response APDU encrypted, MAC protected
    TEE_SC_CR_ENC_MAC = 0x33, // Command, Response APDU encrypted and
    // MAC protected
    TEE_SC_C_ENC_CR_MAC = 0x13 // Command APDU encrypted; Command, Response APDU MAC protected
} TEE_SC_SecurityLevel;

#define TEE_AUTHENTICATE TEE_SC_AUTHENTICATE // deprecated: Command, Response APDU not secured
typedef struct TEE_SC_CardKeyRef {
    uint8_t scKeyID;      // key identifier of the SC card key
    uint8_t scKeyVersion; // key version of the SC card key
} TEE_SC_CardKeyRef;

typedef struct TEE_SC_DeviceKeyRef {
    TEE_SC_KeyType scKeyType; // type of SC keys
    union {
        TEE_ObjectHandle scBaseKeyHandle; // SC base key (acc. to SCP02)
        TEE_SC_KeySetRef scKeySetRef;     // Key-ENC, Key-MAC (acc. to SCP02, SCP03)
    } TEE_keyInner;
#define __TEE_key TEE_keyInner
} TEE_SC_DeviceKeyRef;

typedef struct TEE_SC_OID {
    uint8_t *buffer;    // the value of the OID
    uint32_t bufferLen; // length of the SC OID
} TEE_SC_OID;

typedef struct TEE_SC_Params {
    uint8_t scType;                       // the SC type
    TEE_SC_OID scOID;                     // the SC type defined by OID
    TEE_SC_SecurityLevel scSecurityLevel; // the SC security level
    TEE_SC_CardKeyRef scCardKeyRef;       // reference to SC card keys
    TEE_SC_DeviceKeyRef scDeviceKeyRef;   // reference to SC device keys
} TEE_SC_Params;

#ifdef __cplusplus
extern "C" {
#endif

TEE_Result TEE_SEServiceOpen(TEE_SEServiceHandle *seServiceHandle);
void TEE_SEServiceClose(TEE_SEServiceHandle seServiceHandle);
TEE_Result TEE_SEServiceGetReaders(TEE_SEServiceHandle seServiceHandle, TEE_SEReaderHandle *seReaderHandleList,
    uint32_t *seReaderHandleListLen);
TEE_Result TEE_SEReaderGetName(TEE_SEReaderHandle seReaderHandle, char *readerName, uint32_t *readerNameLen);
TEE_Result TEE_SEReaderOpenSession(TEE_SEReaderHandle seReaderHandle, TEE_SESessionHandle *seSessionHandle);
void TEE_SEReaderCloseSessions(TEE_SEReaderHandle seReaderHandle);
void TEE_SESessionClose(TEE_SESessionHandle seSessionHandle);
void TEE_SESessionCloseChannels(TEE_SESessionHandle seSessionHandle);
TEE_Result TEE_SESessionOpenBasicChannel(TEE_SESessionHandle seSessionHandle, TEE_SEAID *seAid,
    TEE_SEChannelHandle *seChannelHandle);
TEE_Result TEE_SESessionOpenLogicalChannel(TEE_SESessionHandle seSessionHandle, TEE_SEAID *seAid,
    TEE_SEChannelHandle *seChannelHandle);
void TEE_SEChannelClose(TEE_SEChannelHandle seChannelHandle);
TEE_Result TEE_SEChannelGetSelectResponse(TEE_SEChannelHandle seChannelHandle, void *response, uint32_t *responseLen);
TEE_Result TEE_SEChannelTransmit(TEE_SEChannelHandle seChannelHandle, void *command, uint32_t commandLen,
    void *response, uint32_t *responseLen);
TEE_Result TEE_SESecureChannelOpen(TEE_SEChannelHandle seChannelHandle, TEE_SC_Params *params);
void TEE_SESecureChannelClose(TEE_SEChannelHandle seChannelHandle);
#ifdef __cplusplus
}
#endif

#endif // UNIT_TEST_INC_TEE_SE_API_H